All right.
The next thing what we can script on our game is the movement of the player's camera.
The plan is to have the camera see frame set to an invisible part in the workspace, and we want to
be able to move the camera around a little bit based on the position of the player's mouse.
We're also going to be using this module script inside of replicated storage, which is called Camera
Shaker, to easily shake the camera with multiple different presets.
This module script was created by another developer in 2018, and it shows us right here exactly how
we can go ahead and use this module script.
So to get started, let's go ahead and go into starter player scripts.
And we're going to open up our handler section.
And we want to script our camera manipulation handler.
So inside of here we're going to need a few services.
The first service we'll need is the player service.
That way we can get access to the local player.
We want to have a reference to replicated storage.
We'll have a reference to the run service.
That way we can update the position of our camera every single frame.
We'll have a reference to the starter guy and you'll see why in a moment.
And then we're going to have a reference to the tween service.
That way we can smoothly move the position of our camera around.
The next thing we'll have to do is we'll have to create a table for this module script.
Because as you remember, we have to return a table from this module script.
I'm going to call it camera manipulation.
And we'll return it at the very end of our script here.
And that's because we need to have a initialize and start function for this module script.
But before we do that, we'll need some other variables in here.
One is going to be a reference to that camera shaker itself, that module script.
So we'll call it camera shaker and we'll require.
From replicated storage.
And we want to access the modules folder and get our camera shaker.
And we don't have to use Wafer Child because it's already here within the snapshot of our game.
And these scripts won't run until the game has been loaded, so no need to use Wafer Child.
We'll have a reference to the local player so players dot local player we'll have a reference to our
current camera workspace dot current camera.
And then we're going to have a reference to that part in the workspace that we're going to set the camera
C frame to.
So I have an invisible part in here somewhere.
Here it is.
And we're going to have the player's camera basically looking in this general direction.
And when the player's mouse moves around, we kind of want to have the player's camera follow along
with the mouse.
So if it moves down, we'll move the camera down a little bit.
If it goes up, we'll move it up a little bit and so on just to make the game feel a little bit more
interactable.
So we'll call this something like menu camera part.
And it's in the workspace Dot Krusty Krab and it's called menu Camera part.
The last variable we'll need is a reference to the player's mouse.
So we could just do player get mouse.
All right.
Now, some private functions we'll need in here.
One is going to be for enabling the movement of the camera.
So we'll have the camera set up when the initialize function for this module gets run.
And we'll set up the camera movement.
And we're also going to have a function to set up the camera.
Because there's some properties in the camera we'll want to change.
And actually we can fill that out right now.
So in the current camera we want to set the camera type equal to enum dot camera TypeScript label.
That way we can control it through our scripts.
We want to set the key frame of our camera equal to that menu camera parts key frame.
And I want to limit the field of view of our camera so we can set the field of view, not find first
field of view equal to something like 55 degrees.
And then once we've set all that up we can just call our enable camera movement function.
Now down here what we want to do is we want to create a couple functions belonging to this table.
So one function is going to be for initializing this handler or this basically this custom service.
So we're going to call it camera manipulation.
And this function is going to be init for initialize.
And we're also going to have one for starting this handler.
So camera manipulation start.
And all this function is going to do is it's going to call our setup camera function.
Now inside of our initial eyes.
What we want to do here actually, is I want to set the reset button on the player to not be able to
like, be used.
So I don't want to give players the ability to hit escape on their keyboard and then reset themselves
because they're in a lobby, there's no really point for them to reset.
So what we need to do is instead of starter guy, we want to set the core in here.
Of I believe the name is reset button callback and we set this to false.
So what this does is it basically just disables our reset button.
Now one interesting thing to note actually is that the starter GUI or this core scripts may not have
been initialized when we call this function.
So we might get an error message or something in the console that says, uh, the core scripts haven't
been initialized yet.
So what we need to do is we actually need to wrap this function in a p call.
So we could do success.
Results is equal to p call.
We're going to pass starter GUI dot set core or the reference to this function.
And since this function is using the two colons, the first uh argument we need to pass is starter GUI
itself.
Then we can pass our string of reset button callback and then our last argument, which is false.
So in case for some reason the starter GUI or core scripts haven't been initialized, we can check.
So if not successful then we're going to continue trying to disable the players reset button so we can
spawn a loop in here.
And this loop is going to be a repeat loop.
So we're just going to repeat every second of trying to set.
Uh, this here, and we're just going to override success and results with p call.
So we're going to keep repeating this until we are successful in disabling the players reset button.
Now one more thing I want to disable within the starter GUI is the player list, or that list on the
right hand side of the screen that shows all the players in the game.
I just want to disable that to remove as much clutter off the screen as possible.
So in order to do that, we can just reference starter GUI and call a function called Set core GUI enabled.
And we want this to be the core GUI type of player list.
And we just set this to false.
And this is a function we don't have to use p call on.
Okay, so the last thing we need to do here is we need to go ahead and fill out our enable camera movement
function.
So the plan is here is we're going to use the run service to constantly call a function to continually
update the sea frame of our camera.
And because we're going to be updating it every single frame, it's not going to be very wise to call
global functions like sea frame dot new or Vector3 dot new, stuff like that, when we can actually
store a reference to those functions in memory in like local memory.
And it's actually faster doing that way.
So what I'm going to do is I'm going to create a bunch of variables here that reference the global variables
for creating different kind of data types.
So one example we could do is for sea frame new we'll just call it KAF knew.
We want to do one for creating a new vector, three, one for creating a new vector two, and then one
for creating a new tween info.
And we can just set that equal to sea frame dot new.
And we're not calling it.
We're making a reference to this function.
Same thing with vector three dot new, vector two dot new and then tween info dot new.
The next thing I want to do is I want to create a variable.
And I'm going to call this camera shake sea frame or KF for short.
And this is literally just going to be equal to a blank sea frame for now.
But the idea is, is that inside of our camera shaker we have to attach a function in there.
And this function constantly gets called when we enable the camera shaker.
And what this function will do is it'll return back to us the updated keyframe for the camera.
That should give us the correct position.
We need to set on the camera to represent the shake on our screen, so you'll see what I mean in a moment.
But basically what we need to do here is we want to access our camera shaker and we want to create a
new, I believe it's called a camera shake handler.
We need to pass a render priority because it's going to be calling this callback function, uh, binded
to render step.
And you can set the render priority to different levels.
But I just want the render priority to be equal to the camera's render priority, which is in camera
dot value.
And then for the callback function, this function gets called every single time we need to update the
camera keyframe, so it'll pass to us a new keyframe.
We'll just call it camera keyframe.
And what I want to do is I want to constantly update this variable here our camera shake keyframe to
be equal to this newly created keyframe.
So cam keyframe.
Now this constructor here returns back to us another table.
We're just going to call it camera Shake handler, and this camera shake handler has a function in it
actually a bunch of them.
But one of them is to start.
And what this does is it binds this function here that we created to render steps.
And that means this variable here is going to be constantly updated every single frame.
So I'm going to spawn a function and a new thread down here.
And this is just going to loop forever, because what it's going to do is we're going to wait about
like 1.5 seconds, because with our camera shake handler, we want to shake the camera and we can pass
a preset here for how much we want to shake the camera.
So if we actually go inside of our camera shaker, there's some camera shake presets in here.
And they have different names ones bump, explosion, earthquake.
But there is one in here called Light Bounce, which shakes the screen very lightly.
So what we could do here is we could pass camera shaker.
Pass the presets and the preset we want to use is the Light Bounce.
And since we have already started our camera shake handler, that means this camera see frame here is
going to update this variable with the new values that are created when we call the shake function every
1.5 seconds.
So now it is up to us, or it is our responsibility to update the camera see frame, because it's just
going to pass us the see frame itself.
It's not going to update the see frame for us.
We actually need to do that on our own.
So I'm going to create a function inside of here.
And I'm going to call it update cam position.
And what this is going to do is it's going to get the camera's original C frame or aka the exact same
C frame of this part.
So that way the camera is never able to wander off.
We want to stay constricted to the C frame here, and we need to offset the C frame based on the position
of the mouse, and we also need to offset it based on the camera shake.
So when the camera shakes, we need to apply the rotation to make it look like the camera shaking.
So in order to do that, we actually first need to get the coordinates for the center of the screen.
So I'm going to call a variable here called center of screen.
And it's going to be equal to a vector two new.
And what we're going to do is we're going to get the current camera and get the viewport size on the
x axis.
We divide it by two to get the middle of the screen on the x axis.
And then we could do the exact same thing to get the middle of the screen on the y axis.
So now we have a coordinate that's directly in the center of our screen.
And the reason we need a coordinate directly in the center of our screen.
Because that's going to act as our origin point.
So when our mouse moves above the origin point, we want to move the camera up.
When the mouse moves below or to the left or to the right, we want to move it correctly.
And this is because the viewport of our camera's origin actually starts up in the top left corner,
so it's positive in the x axis going this way, and it's positive on the y axis going this way.
So it's a little weird.
So we need to make sure we have the center of the screen to act as our origin point.
Because the next thing I want to do here is I want to create a new tween.
I'm going to call it tween, and we're going to use the tween service to create a new tween.
This twin is going to affect our camera.
And for a new tween info, we can just do something like 0.6 seconds.
So if I move my mouse to over here, it will take about 0.6 seconds to shift the camera to that corresponding
mouse position.
And that means for our property table, we want to update the keyframe of our camera.
To first be equal to the camera's original C frame.
So we want to get the original camera C frame so we can just do current cam dot C frame.
And we want to set it to this original camera C frame.
And then we can add another C frame to offset it based on the mouse's position.
And we're going to do so using a new C frame.
And the reason we're not using a vector here is because I want to shift the camera based on its local
x and y axes, rather than the global X and y axes.
Now, in order to get the correct position of the mouse, what I need to do here is I need to get the
mouse's position by doing mouse dot x, and then I need to subtract it by the center of screen on the
x axis.
So this will give us the pixel position of our mouse.
So let's say my mouse is in the center of the screen.
The x position would be zero because we're subtracting it by the center of the screen.
And then if I move it over to the left we'll get a corresponding number.
Or basically let's say the center of our screen is like 200 pixels.
We move it to the left to 150 pixels.
We'll subtract 150 by 200, and that means we'll get a -50.
So that means we'll want to move the camera to the left.
And then if we go over here and do like 250, then our means our mouse is a positive 50 pixels to the
right of the center of our screen.
And then we're going to do the exact same thing for the y axis.
We just get the mouse's position on the y axis and then subtract it by center of screen dot y.
And then for the z axis, we don't have to worry at all.
So we're just going to set that as zero.
Now one more thing is I also want to multiply or basically add another offset to the key frame which
is going to be the cam shake key frame variable.
So cam shake key frame.
And this will also apply.
You know that shaking of the screen that is produced by our camera shake handler.
Now, one more thing we actually want to make sure that we do is that when a player's character gets
added into the game, it's going to reset the current camera's camera type property back to custom,
which will move the player's camera back to the player's character.
Now, one way we can mitigate this problem is that inside of our setup camera, we can connect an event
to our current camera.
So current cam.
And then we can get property change signal which would be camera type.
And we'll connect a lambda function to this.
And all we want to do is we want to make sure that the camera type of our camera stays as scriptable.
Now, in order to see this in action, what we need to do here is we need to attach this update camera
position to an event inside of a run service.
So run service dot render stepped.
We can go ahead and connect our update camera position function.
So now we can actually go ahead and play and see this camera effect in action.
So currently as you can see our camera is moving way too much because yeah as you can see our camera
is moving actually hundreds of studs because we are representing the camera movement by using the pixels
on the screen.
So since our screen is hundreds of pixels across, when moving the camera around, we're moving it by
hundreds of studs.
So if we want to reduce the amount that we can move the camera, what we need to do is we need to divide
this value here by some amount.
So for example, we could divide this amount by something like 400 and then do it on the same thing
here as well.
And that way we're actually reducing how much, uh, our camera c frame is moving.
So if we go back to play, test this again.
You can see now our camera is moving a lot less, but you may be noticing that it's moving correctly
in the X direction.
But when I do it in the y direction, if I go down, our camera moves up and when I go up, our camera
moves down.
And that's because since our center position will be zero on the y axis, if we increase a number by
going down, we're ending up with a positive pixel compared to the origin point, which is causing our
camera to move up.
And when we go this way, we're ending up with a smaller position with our mouse on the y axis, which
is causing our camera to move down.
So in order to fix that problem, what we could do is we could just reverse this value here by adding
a negative symbol in the front.
Another thing here I'm going to show you is I'm actually going to print this value out inside of the
console.
So let me remove the negative symbol here.
So you can actually go ahead and see what's going on.
So when our mouse is in the center of the screen here, as you can see, it's printing out the position
divided by 400.
So when we reach the center of the screen, it'll print around zero.
And as you can see, when we go down that value is slowly increasing.
And then when we go up it's turning into a negative number.
But of course when we go and negate this value to be negative.
Now when we go and test it, when we go down, it becomes negative.
And when we go up, it becomes positive.
And of course, you're free to go ahead and adjust these values right here to whatever you'd like.
So if you'd like the camera to move more, you could reduce this number by something like 100.
And if we go ahead and test the camera movement now when we go to move the camera around, as you can
see, it's moving a lot more than before.
Now let's go ahead and keep the camera still.
And as you can see, if you look very closely, our camera is shaking just very slightly because we
have that light bounce happening every 1.5 seconds.
And because our update camera position is running every time during this rendered step event, even
if we don't move the camera around, we just keep it at the position of the mouse.
It's still getting that camera shake keyframe applied to it, which is applying that nice little shake
effect on our screen.
So other than that, our camera manipulation handler is complete.
And in the next lecture, we're going to go ahead and get started scripting our starting menu.
So I'll go ahead and see you there.